import * as BABYLON from '@babylonjs/core'
import { Scene, Vector3 } from '@babylonjs/core'
import { YkBabylonScene } from './create3D.ts'
import { useSgesMAStore } from './MountainGesCalA.ts'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'

const store = useSgesMAStore()

const {
  heightMT,
  slopeDegree,
  slopeDistance,
  slopeDegreeRad,
  lengthSlope,
  numRails,
  lengthBlock,
  widthBlock,
  heightBlock,
  widthSlope,
  lengthAccelerate,
  lengthStorage,
  lengthMerge,
  gap_rails,
  height_sleeper,
  radius_wheel,
  thick_wheel,
  totalBlocksNum,
  width_sleeper,
  massBlock
} = storeToRefs(store)

const addition_height = 0.1 // 超过地面的额外高度，否则地面和模型一面重叠，会导致渲染闪烁
const addition_below_y = 10 // 模型低于地面的额外高度，否则地面和模型一面重叠，会导致渲染闪烁
const railWidth = computed(() => Number(gap_rails.value))
const gap = 0.15 // 轮子上边缘和车厢下边缘的间距
const l1 = computed(() => Number(lengthStorage.value) + Number(lengthAccelerate.value) + Number(lengthMerge.value))


/**
 * 绘制山体重力储能场景，以山脚为原点，向右为x轴，向上为z轴，向里为y轴
 * @param ykScene
 */
export const buildScene = (ykScene: YkBabylonScene) => {
  let scene: Scene = ykScene.scene
  console.log('创建场景...')
  ykScene.customData.pickableMeshes = []
  const groundAgg = createGround(ykScene)
  createMountain(ykScene)
  createRails(ykScene)
  createMultipleMineCarts(ykScene, groundAgg) // 调用新的创建多个小车的函数
  createGenerator(ykScene, groundAgg)
  showAxis(scene, 3) // 添加坐标轴指示器，尺寸为100

  // 遍历ykScene.customData.pickableMeshes, 为每个物体添加点击事件
  ykScene.customData.pickableMeshes.forEach(mesh => {
      console.log(mesh, mesh.name)

      mesh.isPickable = true
      mesh.actionManager = new BABYLON.ActionManager(scene)

      mesh!.actionManager!.registerAction(
        new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, function(evt) {
          const name = mesh!.name

          // 确保selected数组已初始化
          if (!ykScene.customData.selected) {
            ykScene.customData.selected = []
          }

          // 检查是否按住了Ctrl键
          const isCtrlPressed = evt.sourceEvent?.ctrlKey || false

          // 如果没有按住Ctrl键，则取消其他物体的选中状态
          if (!isCtrlPressed) {
            // 只遍历当前选中的物体，取消它们的选中状态
            for (const selectedName of ykScene.customData.selected) {
              if (selectedName !== name) {
                const selectedMesh = scene.getMeshByName(selectedName)
                if (selectedMesh) {
                  (selectedMesh as any).isSelected = false
                  if (selectedMesh instanceof BABYLON.InstancedMesh) {
                    selectedMesh.sourceMesh.material = (selectedMesh as any).defaultMaterial
                  } else {
                    selectedMesh.material = (selectedMesh as any).defaultMaterial
                  }
                }
              }
            }

            // 清除选中状态数组，但保留当前点击的物体（稍后处理）
            ykScene.customData.selected = ykScene.customData.selected.filter(selectedName => selectedName === name)
          }

          // 切换当前物体的选中状态
          (mesh as any).isSelected = !(mesh as any).isSelected

          // 更新材质和选中状态数组
          if ((mesh as any).isSelected) {
            if (mesh instanceof BABYLON.InstancedMesh) {
              mesh.sourceMesh.material = ykScene.fireMaterial
            } else {
              mesh.material = ykScene.fireMaterial
            }
            // 如果当前物体不在选中数组中，则添加它
            if (!ykScene.customData.selected.includes(name)) {
              ykScene.customData.selected.push(name)
            }
          } else {
            if (mesh instanceof BABYLON.InstancedMesh) {
              mesh.sourceMesh.material = (mesh as any).defaultMaterial
            } else {
              mesh.material = (mesh as any).defaultMaterial
            }
            // 从选中数组中移除当前物体
            const index = ykScene.customData.selected.indexOf(name)
            if (index > -1) {
              ykScene.customData.selected.splice(index, 1)
            }
          }
        })
      )

    }
  )

}

/**
 * 创建发电机设备
 * @param ykScene
 * @param groundAgg
 */
const createGenerator = (ykScene: YkBabylonScene, groundAgg: BABYLON.PhysicsAggregate) => {
  const railZs = ykScene.customData.railZs
  const depthOfPillars = 0.5
  const diameterOfShaft = 0.5
  const gapOfPillar_Gen = 0.25

  const genNode = new BABYLON.TransformNode('发电机设备')
  const box = BABYLON.MeshBuilder.CreateBox('发电机', {
    width: (Math.min(lengthBlock.value, widthBlock.value) / 2),
    height: heightBlock.value,
    depth: depthOfPillars
  }, ykScene.scene)
  const boxR = BABYLON.MeshBuilder.CreateBox('发电机R', {
    width: (Math.min(lengthBlock.value, widthBlock.value) / 2),
    height: heightBlock.value,
    depth: depthOfPillars
  }, ykScene.scene)

  const shaft = BABYLON.MeshBuilder.CreateCylinder('轴L', {
    height: gapOfPillar_Gen,
    diameter: diameterOfShaft,
    tessellation: 32
  }, ykScene.scene)

  const shaftR = BABYLON.MeshBuilder.CreateCylinder('轴R', {
    height: gapOfPillar_Gen,
    diameter: diameterOfShaft,
    tessellation: 32
  }, ykScene.scene)

  shaft.rotation.x = Math.PI / 2
  shaft.position.z = (widthBlock.value + gapOfPillar_Gen) / 2
  shaft.position.y = heightBlock.value / 2 + addition_height
  shaft.position.x = -lengthMerge.value
  shaftR.rotation.x = Math.PI / 2
  shaftR.position.z = -(widthBlock.value + gapOfPillar_Gen) / 2
  shaftR.position.y = heightBlock.value / 2 + addition_height
  shaftR.position.x = -lengthMerge.value
  box.position.z = widthBlock.value / 2 + gapOfPillar_Gen + depthOfPillars / 2
  box.position.y = heightBlock.value / 2
  box.position.x = -lengthMerge.value
  boxR.position.z = -(widthBlock.value / 2 + gapOfPillar_Gen + depthOfPillars / 2)
  boxR.position.y = heightBlock.value / 2
  boxR.position.x = -lengthMerge.value
  const generator = BABYLON.Mesh.MergeMeshes([box, boxR, shaft, shaftR], true, true, undefined, true)
  generator!.name = '发电机'
  generator!.parent = genNode

  for (let [idx, z] of railZs!.entries()) {
    const generator1 = generator!.createInstance(`发电机${idx}山底`)
    const generator2 = generator!.createInstance(`发电机${idx}山顶`)
    generator1.position.z = z
    generator2.position.z = z
    generator2.position.y = heightMT.value + addition_height
    generator2.position.x = slopeDistance.value + lengthMerge.value * 2
    generator1.parent = genNode
    generator2.parent = genNode

    // new BABYLON.PhysicsAggregate(generator1, BABYLON.PhysicsShapeType.BOX, {
    //   mass: 0,
    //   friction: 0.5,
    //   restitution: 0.5
    // }, ykScene.scene)
    // new BABYLON.PhysicsAggregate(generator2, BABYLON.PhysicsShapeType.BOX, {
    //   mass: 0,
    //   friction: 0.5,
    //   restitution: 0.5
    // }, ykScene.scene)
    ykScene.customData.pickableMeshes?.push(generator1)
    ykScene.customData.pickableMeshes?.push(generator2)
  }
  generator!.isVisible = false
}

/**
 * 沿路径创建多个小车实例
 * @param ykScene
 * @param groundAgg
 */
const createMultipleMineCarts = (ykScene: YkBabylonScene, groundAgg: BABYLON.PhysicsAggregate) => {
  console.log('创建多个重物小车...')
  const railZs = getRailZs()
  ykScene.customData.railZs = railZs
  const numCarts = Math.ceil(totalBlocksNum.value / numRails.value)
  console.log('小车数量:', numCarts)
  const carts = new BABYLON.TransformNode('小车')
  const firstCartX = -l1.value + lengthBlock.value / 2
  let j = 0
  for (let z of railZs) {
    j++
    const cartsZ = new BABYLON.TransformNode(`第${j}轨`)
    for (let i = 0; i < numCarts; i++) {
      const x = firstCartX + i * (lengthBlock.value + 0.001)
      let y = addition_height + 2 * Number(radius_wheel.value) + gap + heightBlock.value / 2 + Number(height_sleeper.value)

      const cart = createMineCartInstance(ykScene, groundAgg, new BABYLON.Vector3(x, y, z), `Cart_${j}_${i}`)
      cart.parent = cartsZ
    }
    cartsZ.parent = carts
  }

}

/**
 * 创建单个小车实例（带物理约束）
 * @param ykScene
 * @param groundAgg
 * @param position
 * @param name
 */
const createMineCartInstance = (ykScene: YkBabylonScene, groundAgg: BABYLON.PhysicsAggregate, position: BABYLON.Vector3, name: string) => {
  const scene = ykScene.scene

  // 获取重物块尺寸参数
  const cartLength = lengthBlock.value
  const cartWidth = widthBlock.value
  const cartHeight = heightBlock.value
  const cartGroup = new BABYLON.TransformNode(name)
  // 创建小车车厢实例
  const cartBodyMesh = BABYLON.MeshBuilder.CreateBox(name, {
    width: cartLength,
    height: cartHeight,
    depth: cartWidth
  }, scene)
  // cartBodyMesh.freezeWorldMatrix() // 按道理不能冻结，但是先冻结再说，需要移动时在恢复

  cartBodyMesh.position.copyFrom(position)

  // 为车厢创建物理属性
  const cartAggregate = new BABYLON.PhysicsAggregate(
    cartBodyMesh,
    BABYLON.PhysicsShapeType.BOX,
    { mass: massBlock.value * 0.6, restitution: 0.1, friction: 0.1 },
    scene
  )
  // 创建约束限制小车在Z轴方向的移动和绕X、Y轴的旋转
  const constraint = new BABYLON.Physics6DoFConstraint(
    {
      pivotA: new BABYLON.Vector3(0, 0, 0),
      pivotB: new BABYLON.Vector3(position.x, position.y, position.z),
      perpAxisA: new BABYLON.Vector3(1, 1, 0),
      perpAxisB: new BABYLON.Vector3(1, 1, 0)
    },
    [
      { axis: BABYLON.PhysicsConstraintAxis.LINEAR_Z, minLimit: 0, maxLimit: 0 },
      { axis: BABYLON.PhysicsConstraintAxis.ANGULAR_X, minLimit: 0, maxLimit: 0 },
      { axis: BABYLON.PhysicsConstraintAxis.ANGULAR_Y, minLimit: 0, maxLimit: 0 },
      {
        axis: BABYLON.PhysicsConstraintAxis.LINEAR_X,
        minLimit: -l1.value + lengthBlock.value,
        maxLimit: slopeDistance.value + l1.value - lengthBlock.value
      }
    ],
    scene
  )

  // 将约束添加到物理体
  cartAggregate.body.addConstraint(groundAgg.body, constraint)

  // 车轮位置参数
  const wheelPositions = [
    // 前左轮
    { x: -cartLength / 3, z: railWidth.value / 2 },
    // 前右轮
    { x: cartLength / 3, z: railWidth.value / 2 },
    // 后左轮
    { x: -cartLength / 3, z: -railWidth.value / 2 },
    // 后右轮
    { x: cartLength / 3, z: -railWidth.value / 2 }
  ]

  const y_pos = -cartHeight / 2 - Number(radius_wheel.value) - gap

  const wheels: any = []
  wheelPositions.forEach((pos, index) => {
    const wheel = BABYLON.MeshBuilder.CreateCylinder(`${name}_wheel${index}`, {
      diameter: Number(radius_wheel.value) * 2,
      height: Number(thick_wheel.value),
      tessellation: 16
    }, scene)

    // 车轮位置必须和车厢的位置符合初始物理约束限制，否则小车初始化时不知道按谁的位置计算会弹飞
    wheel.rotation.x = Math.PI / 2 // 使车轮立起来
    wheel.position.x = cartBodyMesh.position.x + pos.x
    wheel.position.y = addition_height + Number(radius_wheel.value) + Number(height_sleeper.value)
    wheel.position.z = cartBodyMesh.position.z + pos.z

    // 为车轮创建材质
    wheel.material = ykScene.steelMaterial

    const wheelAgg = new BABYLON.PhysicsAggregate(
      wheel,
      BABYLON.PhysicsShapeType.CYLINDER,
      { mass: massBlock.value * 0.1, restitution: 0.1, friction: 0.004 },
      scene
    )

    // 使用HingeConstraint连接车轮和车厢
    const hingeConstraint = new BABYLON.HingeConstraint(
      new BABYLON.Vector3(pos.x, y_pos, pos.z), // 车厢上的连接点
      new BABYLON.Vector3(0, 0, 0), // 车轮中心点
      new BABYLON.Vector3(0, 0, 1), // 绕Z轴旋转
      new BABYLON.Vector3(0, 1, 0), // 车轮的旋转轴
      scene
    )

    // 将约束添加到物理引擎
    cartAggregate.body.addConstraint(wheelAgg.body, hingeConstraint)
    wheel.parent = cartGroup
    wheels.push({ wheel, wheelAgg })

    wheel.freezeWorldMatrix()
    wheelAgg.body.setMotionType(0)
    wheelAgg.body.disableSync = true
  })

  cartBodyMesh.freezeWorldMatrix()
  cartAggregate.body.setMotionType(0)
  cartAggregate.body.disableSync = true

  // 添加点击事件处理

  ykScene.customData.pickableMeshes?.push(cartBodyMesh)


  cartBodyMesh.parent = cartGroup

  return cartGroup
}


// 获取所有轨道的Z坐标
const getRailZs = () => {
  // 确定铁轨在z方向的位置
  const railZs: number[] = []
  if (numRails.value % 2 === 0) {
    // 如果铁轨数量为偶数，则两条铁轨对称布置在z=0的两边，间距为Number(widthSlope.value)
    railZs.push(-Number(widthSlope.value) / 2)
    railZs.push(Number(widthSlope.value) / 2)
    let i = 1
    while (railZs.length < numRails.value) {
      i = i + 2
      railZs.push(-Number(widthSlope.value) / 2 * i)
      railZs.push(Number(widthSlope.value) / 2 * i)
    }
  } else {
    // 如果铁轨数量为奇数，则两条铁轨分别布置在z=0的两侧，间距为Number(widthSlope.value)
    railZs.push(0)
    let i = 1
    while (railZs.length < numRails.value) {
      i = i + 1
      railZs.push(-Number(widthSlope.value) * i)
      railZs.push(Number(widthSlope.value) * i)
    }
  }
  return railZs
}

/**
 * 创建铁轨
 * @param ykScene
 */
const createRails = (ykScene) => {
  console.log('创建铁轨...')
  const scene = ykScene.scene
  const railNode = new BABYLON.TransformNode('轨道')

  // 重载铁路截面尺寸（单位：米）
  const railHeadWidth = 0.07     // 轨头宽度
  const railHeadHeight = 0.04    // 轨头高度
  const railWebThickness = 0.02  // 轨腰厚度
  const railBaseWidth = 0.12     // 轨底宽度
  const railBaseHeight = 0.03    // 轨底高度
  const railHeight = railHeadHeight + railWebThickness + railBaseHeight // 轨道总高度

  // 创建铁轨截面形状（梯形头+矩形腰+梯形底）
  const railProfile = [
    new Vector3(-railHeadWidth / 2, railHeight - railHeadHeight, 0),      // 轨头左上
    new Vector3(railHeadWidth / 2, railHeight - railHeadHeight, 0),       // 轨头右上
    new Vector3(railWebThickness / 2, railBaseHeight + railWebThickness, 0), // 轨腰右上
    new Vector3(railBaseWidth / 2, railBaseHeight, 0),                   // 轨底右
    new Vector3(-railBaseWidth / 2, railBaseHeight, 0),                  // 轨底左
    new Vector3(-railWebThickness / 2, railBaseHeight + railWebThickness, 0) // 轨腰左上
  ]

  // 确定铁轨在z方向的位置
  const railZs: number[] = getRailZs()

  // 根据距离获取路径上的点和切线
  const getPathPointAtDistance = (path3d: BABYLON.Path3D, distance: number) => {
    const pathPoints = path3d.getCurve()
    let currentDistance = 0
    for (let i = 1; i < pathPoints.length; i++) {
      const segmentLength = pathPoints[i].subtract(pathPoints[i - 1]).length()
      if (currentDistance + segmentLength >= distance) {
        // 在当前线段上插值
        const segmentRatio = (distance - currentDistance) / segmentLength
        const position = BABYLON.Vector3.Lerp(pathPoints[i - 1], pathPoints[i], segmentRatio)
        let tangent = new Vector3(1, 0, 0)
        if (i === 1 || i === 3) {

        } else if (i === 2) {
          tangent = new Vector3(pathPoints[i].x - pathPoints[i - 1].x, pathPoints[i].y - pathPoints[i - 1].y, 0).normalize()
        }

        return { position, tangent }
      }
      currentDistance += segmentLength
    }

    // 如果超出路径长度，返回最后一个点
    return {
      position: pathPoints[pathPoints.length - 1],
      tangent: new Vector3(1, 0, 0)
    }
  }


  const createSleepersAlongPath = (path: Vector3[], ykScene, railIndex: number) => {
    const sleeperSpacing = 1.65 // 枕木间距，单位为米
    const scene = ykScene.scene
    // 创建一个枕木的基本形状，作为实例化的源
    const sleeperSource = BABYLON.MeshBuilder.CreateBox('sleeperSource', {
      width: Number(width_sleeper.value),    // 枕木宽度
      height: Number(height_sleeper.value),  // 枕木高度
      depth: railWidth.value + 0.3 // 枕木长度，略长于轨距
    }, scene)
    // sleeperSource.material = ykScene.marbleMaterial // 将材质应用到源网格上
    sleeperSource.isVisible = false // 隐藏源网格
    sleeperSource.freezeWorldMatrix()

    sleeperSource.parent = railNode

    // 计算路径总长度
    let pathLength = 0
    for (let i = 1; i < path.length; i++) {
      pathLength += path[i].subtract(path[i - 1]).length()
    }

    // 计算需要的枕木数量
    const sleeperCount = Math.floor(pathLength / sleeperSpacing)
    // 创建Path3D对象用于获取路径上的点和切线
    const path3d = new BABYLON.Path3D(path)

    // 建一个空 Transform，用于折叠所有的InstanceMesh，因为InstanceMesh不是网格，无法合并
    const instanceRoot = new BABYLON.TransformNode(`枕木阵列${railIndex + 1}`, scene)
    // instanceRoot.setEnabled(false) // 让 Inspector 不再展开它

    for (let i = 0; i <= sleeperCount; i++) {
      // 计算枕木在路径上的位置（弧长参数化）
      const distance = i * sleeperSpacing // 第i个枕木在路径上的位置
      if (distance > pathLength) break // 如果已经超出路径长度，则停止创建枕木

      // 获取路径上指定距离的点和切线
      const point = getPathPointAtDistance(path3d, distance)

      // 创建枕木实例
      const sleeper = sleeperSource.createInstance(`sleeper_${railIndex}_${i}`)
      sleeper.position.x = point.position.x
      sleeper.position.y = point.position.y
      sleeper.position.z = point.position.z + (railWidth.value) / 2

      // 根据路径方向旋转枕木
      sleeper.rotationQuaternion = BABYLON.Quaternion.FromEulerAngles(0, 0, Math.atan2(point.tangent.y, point.tangent.x))
      // 将枕木添加到TransformNode中
      sleeper.parent = instanceRoot
      sleeper.freezeWorldMatrix()
    }

    instanceRoot.parent = railNode
  }

  for (let idx in railZs) {
    // 创建两条铁轨路径点
    const z = railZs[idx]
    const z1 = z - gap_rails.value / 2
    const z2 = z + gap_rails.value / 2
    const railPath1 = [
      new Vector3(-l1.value, addition_height + Number(height_sleeper.value), z1),
      new Vector3(0, addition_height + Number(height_sleeper.value), z1),
      new Vector3(slopeDistance.value, heightMT.value + addition_height + Number(height_sleeper.value), z1),
      new Vector3(l1.value + slopeDistance.value, heightMT.value + addition_height + Number(height_sleeper.value), z1)
    ]
    const railPath2 = [
      new Vector3(-l1.value, addition_height + Number(height_sleeper.value), z2),
      new Vector3(0, addition_height + Number(height_sleeper.value), z2),
      new Vector3(slopeDistance.value, heightMT.value + addition_height + Number(height_sleeper.value), z2),
      new Vector3(l1.value + slopeDistance.value, heightMT.value + addition_height + Number(height_sleeper.value), z2)
    ]
    // 创建两条铁轨实体
    const leftRail = BABYLON.MeshBuilder.ExtrudeShape(`leftRail${idx}`, {
      shape: railProfile,
      path: railPath1,
      cap: BABYLON.Mesh.CAP_ALL
    }, scene)

    const rightRail = BABYLON.MeshBuilder.ExtrudeShape(`rightRail${idx}`, {
      shape: railProfile,
      path: railPath2,
      cap: BABYLON.Mesh.CAP_ALL
    }, scene)

    const rail = BABYLON.Mesh.MergeMeshes([leftRail, rightRail], true, true, undefined, true)
    if (rail) {
      rail.name = `rail${idx}`
      // 设置铁轨颜色为红色以便观察
      const railMaterial = new BABYLON.StandardMaterial('railMaterial', scene)
      railMaterial.diffuseColor = new BABYLON.Color3(1, 0, 0) // 红色

      rail.material = railMaterial
      rail.freezeWorldMatrix()
      rail.parent = railNode

    }
    createSleepersAlongPath(railPath1, ykScene, parseInt(idx))
  }
}

/**
 * 创建无限大地平面，充满天空盒子区域
 * @param ykScene
 */
const createGround = (ykScene: YkBabylonScene) => {
  console.log('创建地面...')

  // 创建无限大地平面
  const ground = BABYLON.MeshBuilder.CreateGround('地面', {
    width: 10000,
    height: 10000,
    subdivisions: 2,
    updatable: true
  }, ykScene.scene)

  // 应用材质到地面
  ground.material = ykScene.grassMaterial
  // 调整地面位置，使其在原点下方
  ground.position.y = 0

  // 使用 PhysicsAggregate 替代 PhysicsImpostor
  return new BABYLON.PhysicsAggregate(
    ground,
    BABYLON.PhysicsShapeType.BOX,
    { mass: 0, restitution: 0, friction: 1 },
    ykScene.scene
  )
}

/**
 * 创建山坡，以山坡脚下为远点
 * @param ykScene
 */
const createMountain = (ykScene: YkBabylonScene) => {
  console.log('创建山体...')
  const scene = ykScene.scene
  const mountainNode = new BABYLON.TransformNode('山体', scene)

  const mesh1 = BABYLON.MeshBuilder.CreateBox('mountDown', {
    width: l1.value, // x方向
    height: addition_height + addition_below_y, // y轴
    depth: Number(widthSlope.value) * numRails.value * 10 // z轴
  })
  mesh1!.position.y = (addition_height - addition_below_y) / 2
  mesh1!.position.x = -l1.value / 2

  mesh1.material = ykScene.createMaterial(undefined, 100, 100)

  // 为mesh1添加物理属性
  new BABYLON.PhysicsAggregate(
    mesh1,
    BABYLON.PhysicsShapeType.BOX,
    { mass: 0, restitution: 0.1, friction: 1.8 },
    scene
  )

  const mesh2 = BABYLON.MeshBuilder.CreateBox('mountUp', {
    width: l1.value + slopeDistance.value,
    height: heightMT.value + addition_height + addition_below_y,
    depth: Number(widthSlope.value) * numRails.value * 10
  })
  mesh2.position.y = (heightMT.value + addition_height - addition_below_y) / 2
  mesh2.position.x = slopeDistance.value + (l1.value + slopeDistance.value) / 2

  mesh2.material = ykScene.createMaterial(undefined, 100, 100)

  // 为mesh2添加物理属性
  new BABYLON.PhysicsAggregate(
    mesh2,
    BABYLON.PhysicsShapeType.BOX,
    { mass: 0, restitution: 0.1, friction: 1.8 },
    scene
  )

  let _h = 2 * heightMT.value + addition_height + addition_below_y
  const mesh3 = BABYLON.MeshBuilder.CreateBox('mountSlope', {
    width: lengthSlope.value,
    height: _h,
    depth: Number(widthSlope.value) * numRails.value * 10
  })
  // 先旋转，在移动
  mesh3.position.x = lengthSlope.value / 2
  mesh3.position.y = -_h / 2 + addition_height
  mesh3.setPivotPoint(new Vector3(-146.19022000815437, 104.95, 0))
  mesh3.rotation.z = slopeDegreeRad.value

  // 为mesh3创建材质并设置颜色（蓝色）
  mesh3.material = ykScene.createMaterial(undefined, 100, 100)
  new BABYLON.PhysicsAggregate(
    mesh3,
    BABYLON.PhysicsShapeType.BOX,
    { mass: 0, restitution: 0.1, friction: 1.8 },
    scene
  )
  // 不合并网格，因为物理属性检测性能开销问题，合并后不能使用BABYLON.PhysicsShapeType.BOX作为PhysicsAggregate，
  // 导致计算量大幅增大，因此不建议合并网格

  mesh1.parent = mountainNode
  mesh2.parent = mountainNode
  mesh3.parent = mountainNode
}

/**
 * 显示坐标轴指示器
 * @param scene 场景
 * @param size 坐标轴大小
 */
const showAxis = (scene: Scene, size: number) => {
  const makeTextPlane = (text: string, color: string, size: number) => {
    const dynamicTexture = new BABYLON.DynamicTexture('DynamicTexture', 50, scene, true)
    dynamicTexture.hasAlpha = true
    dynamicTexture.drawText(text, 5, 40, 'bold 36px Arial', color, 'transparent', true)
    const plane = BABYLON.MeshBuilder.CreatePlane('TextPlane', { size: size / 2 }, scene)
    const material = new BABYLON.StandardMaterial('TextPlaneMaterial', scene)
    material.backFaceCulling = false
    material.specularColor = new BABYLON.Color3(0, 0, 0)
    material.diffuseTexture = dynamicTexture
    plane.material = material
    // 设置为公告牌模式，始终面向摄像机
    plane.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL
    return plane
  }

  // 创建一个轴心点，用于放置坐标轴系统
  const axisRoot = new BABYLON.TransformNode('坐标轴')

  const axisX = BABYLON.MeshBuilder.CreateLines('axisX', {
    points: [
      BABYLON.Vector3.Zero(),
      new BABYLON.Vector3(size, 0, 0),
      new BABYLON.Vector3(size * 0.95, 0.05 * size, 0),
      new BABYLON.Vector3(size, 0, 0),
      new BABYLON.Vector3(size * 0.95, -0.05 * size, 0)
    ]
  }, scene)
  axisX.color = new BABYLON.Color3(1, 0, 0)
  axisX.parent = axisRoot

  const xChar = makeTextPlane('X', 'red', size / 10)
  // 将X标签位置稍微抬高，避免与地面重叠
  xChar.position = new BABYLON.Vector3(0.9 * size, 0.05 * size, 0)
  xChar.parent = axisRoot

  const axisY = BABYLON.MeshBuilder.CreateLines('axisY', {
    points: [
      BABYLON.Vector3.Zero(),
      new BABYLON.Vector3(0, size, 0),
      new BABYLON.Vector3(-0.05 * size, size * 0.95, 0),
      new BABYLON.Vector3(0, size, 0),
      new BABYLON.Vector3(0.05 * size, size * 0.95, 0)
    ]
  }, scene)
  axisY.color = new BABYLON.Color3(0, 1, 0)
  axisY.parent = axisRoot

  const yChar = makeTextPlane('Y', 'green', size / 10)
  yChar.position = new BABYLON.Vector3(0, 0.9 * size, -0.05 * size)
  yChar.parent = axisRoot

  const axisZ = BABYLON.MeshBuilder.CreateLines('axisZ', {
    points: [
      BABYLON.Vector3.Zero(),
      new BABYLON.Vector3(0, 0, size),
      new BABYLON.Vector3(0, -0.05 * size, size * 0.95),
      new BABYLON.Vector3(0, 0, size),
      new BABYLON.Vector3(0, 0.05 * size, size * 0.95)
    ]
  }, scene)
  axisZ.color = new BABYLON.Color3(0, 0, 1)
  axisZ.parent = axisRoot

  const zChar = makeTextPlane('Z', 'blue', size / 10)
  // 将Z标签位置稍微抬高，避免与地面重叠
  zChar.position = new BABYLON.Vector3(0, 0.05 * size, 0.9 * size)
  zChar.parent = axisRoot

  // 设置坐标轴系统始终以固定大小显示
  scene.registerBeforeRender(() => {
    if (scene.activeCamera) {
      // 计算距离并调整坐标轴大小
      const distance = scene.activeCamera.position.length()
      const scale = Math.max(1, distance / 10)
      axisRoot.scaling = new BABYLON.Vector3(scale, scale, scale)
    }
  })
}
